#include "devicewidget.h"
#include "dm/dmdef.h"
#include "globalconfig.h"


DevWidget::DevWidget(const DevInfo &info, QWidget *parent)
    : AGroupBox{parent}
    , m_info{info}
{
    button = new APushButton(tr(LABEL_DISCONNECT), this);
    waitDialog = new WaitDialog(this);

    button->setMaximumWidth(500);
    button->setCheckable(true);

    auto layout = new QVBoxLayout(this);
    layout->addWidget(button);
    layout->addWidget(new AHLine(this));

    connect(button, &APushButton::toggled, this, &DevWidget::buttonToggled);
    // ui->device
    connect(this, &DevWidget::openDevice, &GlobalConfig::getInstance(), &GlobalConfig::open);
    connect(this, &DevWidget::closeDevice, &GlobalConfig::getInstance(), &GlobalConfig::close);
    connect(&GlobalConfig::getInstance(), &GlobalConfig::connected, this, [&](const DevInfo &info) {
        if (info == m_info) {
            button->setChecked(true);
            button->setText(tr(LABEL_CONNECTED));
        }
    });
    connect(&GlobalConfig::getInstance(), &GlobalConfig::disconnected, this, [&](const DevInfo &info) {
        if (info == m_info) {
            button->setChecked(false);
            button->setText(tr(LABEL_DISCONNECT));
        }
    });
    connect(&GlobalConfig::getInstance(), &GlobalConfig::initialized, waitDialog, &WaitDialog::close);
}

DevWidget::~DevWidget()
{
    emit closeDevice(m_info);
}

DevInfo DevWidget::info() const
{
    return m_info;
}

void DevWidget::buttonToggled(bool checked)
{
    if (checked) {
        emit openDevice(m_info);
        waitDialog->exec();
    }
    else {
        emit closeDevice(m_info);
    }
}

HIDWidget::HIDWidget(const DevInfo &info, QWidget *parent)
    : DevWidget{info, parent}
{
    vidLabel = new ALabel(tr(LABEL_HID_V_ID), this);
    pidLabel = new ALabel(tr(LABEL_HID_P_ID), this);
    // uidLabel = new ALabel(tr(LABEL_HID_U_ID), this);
    vidLineEdit = new ALineEdit(this);
    pidLineEdit = new ALineEdit(this);
    // uidLineEdit = new ALineEdit(this);

    vidLineEdit->setReadOnly(true);
    pidLineEdit->setReadOnly(true);
    // uidLineEdit->setReadOnly(true);

    auto cLayout = new QGridLayout;

    cLayout->addWidget(vidLabel, 0, 0);
    cLayout->addWidget(pidLabel, 1, 0);
    // cLayout->addWidget(uidLabel, 2, 0);
    cLayout->addWidget(vidLineEdit, 0, 1);
    cLayout->addWidget(pidLineEdit, 1, 1);
    // cLayout->addWidget(uidLineEdit, 2, 1);

    auto pLayout = qobject_cast<QVBoxLayout*>(this->layout());
    if (pLayout) {
        pLayout->addLayout(cLayout);
    }
    else {
        setLayout(cLayout);
    }

    vidLineEdit->setText(QString::fromStdString(info.id));
    pidLineEdit->setText(QString::fromStdString(info.desc));
}

SerialWidget::SerialWidget(const DevInfo &info, QWidget *parent)
    : DevWidget{info, parent}
{
    serialLabel = new ALabel(tr(LABEL_SERIAL_PORT), this);
    baudRateLabel = new ALabel(tr(LABEL_SERIAL_BAUD_RATE), this);
    serialLineEdit = new ALineEdit(this);
    baudRateLineEdit = new ALineEdit(this);

    serialLineEdit->setReadOnly(true);
    baudRateLineEdit->setReadOnly(true);

    auto cLayout = new QGridLayout;

    cLayout->addWidget(serialLabel, 0, 0);
    cLayout->addWidget(baudRateLabel, 1, 0);
    cLayout->addWidget(serialLineEdit, 0, 1);
    cLayout->addWidget(baudRateLineEdit, 1, 1);

    auto pLayout = qobject_cast<QVBoxLayout*>(this->layout());
    if (pLayout) {
        pLayout->addLayout(cLayout);
    }
    else {
        setLayout(cLayout);
    }
    serialLineEdit->setText(QString::fromStdString(info.id));
    baudRateLineEdit->setText(QString::fromStdString(info.desc));
}

DeviceWidget::DeviceWidget(QWidget *parent)
    : AGroupBox{tr(LABEL_DEVICE_LIST), parent}
{
    setMinimumWidth(200);

    auto layout = new QVBoxLayout(this);
    layout->setContentsMargins(0, 10, 0, 10);

    scrollArea = new AScrollArea(this);

    layout->addWidget(scrollArea);

    widget = new AWidget(this);

    devLayout = new QVBoxLayout;
    auto wLayout = new QVBoxLayout(widget);

    searchButton = new APushButton(tr(LABEL_SEARCH), widget);
    searchButton->setMaximumWidth(500);

    auto bLayout = new QVBoxLayout;

    bLayout->addWidget(searchButton);
    bLayout->addWidget(new AHLine(this));

    wLayout->addLayout(bLayout);
    wLayout->addLayout(devLayout);
    wLayout->addStretch();

    scrollArea->setWidget(widget);
    scrollArea->setWidgetResizable(true);

    connect(searchButton, &APushButton::clicked, this, &DeviceWidget::serachClicked);

    serachClicked();
}

void DeviceWidget::createVirtualDevice()
{
    createDevice(DmComm::getInstance().getDeviceInfo(true));
}

void DeviceWidget::serachClicked()
{
    createDevice(DmComm::getInstance().getDeviceInfo(false));
}

void DeviceWidget::createDevice(const std::vector<DevInfo> &infos)
{
    auto it = m_list.begin();
    while (it != m_list.end()) {
        bool exists = false;
        for (const auto& new_info : infos) {
            if ((*it)->info() == new_info) {
                exists = true;
                break;
            }
        }
        if (!exists) {
            delete *it;
            it = m_list.erase(it);
        } else {
            ++it;
        }
    }

    for (const auto& new_info : infos) {
        if (!isInfoExistsInList(new_info)) {
            DevWidget *dev = nullptr;
            switch (new_info.type) {
            case DevType::Virtual:
                dev = new HIDWidget(new_info, this);
                break;
            case DevType::HID:
                dev = new HIDWidget(new_info, this);
                break;
            case DevType::Serial:
                dev = new SerialWidget(new_info, this);
                break;
            case DevType::Network:
                // dev = new NetworkWidget(new_info, this);
                break;
            default:
                break;
            }
            if (dev != nullptr) {
                devLayout->addWidget(dev, 0, Qt::AlignHCenter);
                m_list.push_back(dev);
            }
        }
    }
}

bool DeviceWidget::isInfoExistsInList(const DevInfo &targetInfo)
{
    for (auto &widget : m_list) {
        if (widget->info() == targetInfo) {
            return true;
        }
    }
    return false;
}



